/*
 * @Author: OreoWang
 * @Email: ihc523@163.com
 * @Date: 2020-06-01 12:05:23
 * @LastEditors: OreoWang
 * @LastEditTime: 2022-08-17 16:38:31
 * @Description: 数据模型绑定（基于vue）
 */

import { Node, Component, Label, EditBox, Toggle, isValid, RichText, VERSION } from "cc";
import { EDITOR } from "cc/env";

import IViewTemplate from "./IViewTemplate";
import VueLite from "./VueLite";
import { logger } from "./ViewLogger";
import { viewCompiler } from "./compiler/ViewCompiler";
import IViewRender from "./IViewRender";
// import ViewModel from "./ViewModel";

export type CompileTemplate = () => IViewRender;

/**
 * 当前环境是否支持运行时
 * @returns 
 */
export function isSupportRuntime() {
    if(EDITOR){
        let version = VERSION || "0.0.0";
        //3.6.0版本及以上需要支持编辑器预览模式
        if(version.localeCompare("3.6.0")<0){
            return false;
        }
    }
    return true;
}

// 编译模板
function compile(vm: any, template: any, computed: any) {
    // 遍历全部的 template 元素
    Object.keys(template).forEach((attr: string) => {
        let elements = template[attr];
        if (!(elements instanceof Array)) {
            elements = [elements];
        }

        // computed 计算属性没有 setter
        let hasSetter = computed?.[attr] ? false : true;

        elements.forEach((element: Node | Component) => {
            if (typeof vm[attr] !== 'undefined') {
                if (isValid(element)) {
                    if (element instanceof Component) {
                        viewCompiler.bindElement(vm, attr, element, hasSetter);
                    }
                    else {
                        let components = element.getComponents(Component);
                        for (let index = 0; index < components.length; index++) {
                            let component = components[index];
                            viewCompiler.bindElement(vm, attr, component, hasSetter);
                        }
                    }
                }
            }
            else {
                console.warn("绑定对象属性不存在：attr=" + attr);
            }
        });
    })
}

function isVueModel(vm: any) {
    if (vm && vm._isVue && typeof vm.$destroy == 'function') {
        return true;
    }
    return false;
}

class ViewTool {
    /**
     * 创建一个模型
     * @param options 
     */
    static create(options: {
        data: any | { [propName: string]: string },
        template: IViewTemplate,
        computed?: { [propName: string]: Function | { get: Function, set: Function } },
        watch?: { [propName: string]: Function },
        methods?: { [propName: string]: Function },
    }) {
        if (!options || typeof options != 'object') {
            logger.error("ViewTool.creator options 不合法");
            return null;
        }
        if (!options.data || typeof options.data != 'object') {
            logger.error("ViewTool.creator options.data 不合法");
            return null;
        }

        let model = options.data || {};
        let template = options.template;
        if (options.template) {
            //@ts-ignore
            delete options.template;
        }
        if (options.computed) {
            for (const key in model) {
                if (options.computed[key]) {
                    delete model[key];
                }
            }
        }
        // let vm = new win.Vue(options);
        let vm: Vue = VueLite.create(options);
        if (template) {
            compile(vm, template, options.computed);
        }
        return vm;
    }

    /**
     * 销毁一个模型
     * @param model 
     */
    static destroy(vm: any) {
        if (isVueModel(vm)) {
            vm.$destroy();
        }
    }

    
    static createViewModel(compile: CompileTemplate){
        let options = compile();
        !options ? options = {
            data:{},
            template:{},
        } : 0;
        !options.data ? options.data = {} : 0;
        !options.template ? options.template = {} : 0;

        let vm = ViewTool.create(options);
        return vm;
    }
}

export { ViewTool/*, Vue*/ };